#ifndef DUALCANVASRENDERER_H
#define DUALCANVASRENDERER_H

#include <QObject>
#include <QImage>
#include <QSize>
#include <QSizeF>
#include <QCache>
#include <QMutex>
#include <QPainter>
#include <QScreen>
#include <memory>

#include "displaycanvascalculator.h"
#include "processingsettings.h"
#include "virtualcanvasmanager.h"

// 前向声明
struct ProcessingSettings;

/**
 * 双画布渲染器 - 核心渲染引擎
 * 职责：管理物理画布和虚拟画布的协调渲染
 *
 * Martin Fowler重构原则：
 * - Extract Class: 从UnifiedPageRenderer中提取双缓冲逻辑
 * - Introduce Parameter Object: 使用CanvasConfig统一配置参数
 * - Replace Method: 用对象方法替换静态渲染调用
 *
 * 架构模式：双缓冲渲染
 * - 物理画布（DisplayCanvas）：固定尺寸，基于显示器DPI
 * - 虚拟画布（VirtualCanvas）：可变尺寸，基于处理DPI
 */
class DualCanvasRenderer : public QObject
{
    Q_OBJECT

public:
    /**
     * Canvas配置参数对象
     * 重构原则：Introduce Parameter Object - 将相关参数组织到一个对象中
     */
    struct CanvasConfig {
        // === 显示器配置 ===
        DisplayCanvasCalculator::DisplayInfo displayInfo;  // 显示器信息
        QSize displaySize;                                  // 显示器物理尺寸（像素）
        double displayDpi;                                  // 显示器DPI

        // === 处理配置 ===
        double processingDpi;                               // 处理DPI（影响虚拟画布分辨率）
        QSizeF pageSizeMM;                                  // 页面物理尺寸（毫米，通常为A4）

        // === 质量配置 ===
        bool useHighQualityScaling;                         // 是否使用高质量缩放
        Qt::TransformationMode scalingMode;                 // 缩放模式

        // === 构造函数 ===
        CanvasConfig();

        // === 计算方法 ===
        /**
         * 计算物理画布尺寸（基于显示器DPI的固定尺寸）
         * @return 物理画布像素尺寸
         */
        QSize calculatePhysicalCanvasSize() const;

        /**
         * 计算虚拟画布尺寸（基于处理DPI的可变尺寸）
         * @return 虚拟画布像素尺寸
         */
        QSize calculateVirtualCanvasSize() const;

        /**
         * 计算从虚拟画布到物理画布的缩放比例
         * @return 缩放比例
         */
        double getScaleFactor() const;

        /**
         * 验证配置的有效性
         * @return 如果配置有效返回true
         */
        bool isValid() const;

        /**
         * 获取配置的调试信息
         * @return 格式化的配置信息字符串
         */
        QString getDebugInfo() const;
    };

    /**
     * 渲染上下文
     * 包含单次渲染所需的所有信息
     */
    struct RenderContext {
        QImage sourceContent;           // 源内容图像
        ProcessingSettings settings;    // 处理设置
        int pageNumber;                 // 页码
        int totalPages;                 // 总页数
        bool enablePageDecorations;     // 是否启用页面装饰（页码、边距等）

        RenderContext() : pageNumber(0), totalPages(0), enablePageDecorations(true) {}
    };

public:
    explicit DualCanvasRenderer(QObject* parent = nullptr);
    ~DualCanvasRenderer() override;

    // === 配置管理 ===

    /**
     * 设置画布配置
     * @param config 新的画布配置
     */
    void setCanvasConfig(const CanvasConfig& config);

    /**
     * 获取当前画布配置
     * @return 当前配置
     */
    const CanvasConfig& getCanvasConfig() const;

    /**
     * 更新处理DPI（保持其他配置不变）
     * @param newDpi 新的处理DPI
     */
    void updateProcessingDpi(double newDpi);

    /**
     * 自动检测并设置最佳配置
     * @param screen 目标屏幕，nullptr表示主屏幕
     */
    void autoConfigureForDisplay(QScreen* screen = nullptr);

    // === 主要渲染接口 ===

    /**
     * 渲染用于显示的图像（返回物理画布尺寸的图像）
     * 这是预览窗口使用的方法
     * @param context 渲染上下文
     * @return 适合显示的图像
     */
    QImage renderForDisplay(const RenderContext& context);

    /**
     * 渲染用于PDF导出的图像（返回虚拟画布尺寸的图像）
     * 这是PDF导出使用的方法
     * @param context 渲染上下文
     * @return 高分辨率的PDF图像
     */
    QImage renderForPDF(const RenderContext& context);

    /**
     * 渲染到指定的绘制器（用于直接绘制）
     * @param painter 目标绘制器
     * @param targetRect 目标矩形区域
     * @param context 渲染上下文
     * @param forcePhysicalCanvas 是否强制使用物理画布尺寸
     */
    void renderToPainter(QPainter* painter, const QRect& targetRect,
                        const RenderContext& context, bool forcePhysicalCanvas = true);

    // === 画布信息查询 ===

    /**
     * 获取物理画布尺寸
     * @return 物理画布像素尺寸
     */
    QSize getPhysicalCanvasSize() const;

    /**
     * 获取虚拟画布尺寸
     * @return 虚拟画布像素尺寸
     */
    QSize getVirtualCanvasSize() const;

    /**
     * 获取当前缩放比例
     * @return 从虚拟画布到物理画布的缩放比例
     */
    double getCurrentScaleFactor() const;

    /**
     * 检查配置是否已初始化
     * @return 如果配置有效返回true
     */
    bool isConfigured() const;

    // === 缓存管理 ===

    /**
     * 清除所有缓存
     */
    void clearCache();

    /**
     * 清除指定DPI的缓存
     * @param dpi 要清除的DPI值
     */
    void clearCacheForDpi(double dpi);

    /**
     * 获取缓存使用情况
     * @return 缓存统计信息
     */
    QString getCacheStats() const;

signals:
    /**
     * 配置发生变化时发出
     * @param oldConfig 旧配置
     * @param newConfig 新配置
     */
    void configChanged(const CanvasConfig& oldConfig, const CanvasConfig& newConfig);

    /**
     * 渲染开始时发出
     * @param context 渲染上下文
     */
    void renderingStarted(const RenderContext& context);

    /**
     * 渲染完成时发出
     * @param context 渲染上下文
     * @param renderTime 渲染耗时（毫秒）
     */
    void renderingFinished(const RenderContext& context, qint64 renderTimeMs);

private:
    // === 核心渲染方法 ===

    /**
     * 创建或获取虚拟画布
     * @param context 渲染上下文
     * @return 渲染好的虚拟画布
     */
    QImage getOrCreateVirtualCanvas(const RenderContext& context);

    /**
     * 将虚拟画布缩放到物理画布
     * @param virtualCanvas 虚拟画布图像
     * @return 缩放后的物理画布图像
     */
    QImage scaleToPhysicalCanvas(const QImage& virtualCanvas);

    /**
     * 在虚拟画布上渲染内容
     * @param context 渲染上下文
     * @return 渲染好的虚拟画布
     */
    QImage createVirtualCanvas(const RenderContext& context);

    /**
     * 渲染页面内容到指定画布
     * @param painter 绘制器
     * @param canvasSize 画布尺寸
     * @param context 渲染上下文
     */
    void renderPageContent(QPainter& painter, const QSize& canvasSize, const RenderContext& context);

    /**
     * 渲染页面装饰（边距、页码等）
     * @param painter 绘制器
     * @param canvasSize 画布尺寸
     * @param context 渲染上下文
     */
    void renderPageDecorations(QPainter& painter, const QSize& canvasSize, const RenderContext& context);

    /**
     * 计算内容在画布中的位置和大小
     * @param contentSize 内容原始尺寸
     * @param canvasSize 画布尺寸
     * @return 内容在画布中的矩形区域
     */
    QRect calculateContentRect(const QSize& contentSize, const QSize& canvasSize) const;

    // === 缓存相关方法 ===

    /**
     * 生成缓存键
     * @param context 渲染上下文
     * @param dpi 目标DPI
     * @return 缓存键字符串
     */
    QString generateCacheKey(const RenderContext& context, double dpi) const;

    /**
     * 检查缓存中是否存在指定内容
     * @param cacheKey 缓存键
     * @return 如果存在返回true
     */
    bool hasCachedCanvas(const QString& cacheKey) const;

    /**
     * 从缓存获取画布
     * @param cacheKey 缓存键
     * @return 缓存的画布，如果不存在返回空图像
     */
    QImage getCachedCanvas(const QString& cacheKey) const;

    /**
     * 将画布存入缓存
     * @param cacheKey 缓存键
     * @param canvas 要缓存的画布
     */
    void setCachedCanvas(const QString& cacheKey, const QImage& canvas);

private:
    // === 成员变量 ===
    CanvasConfig m_config;                              // 当前画布配置
    bool m_configInitialized;                           // 配置是否已初始化

    // 缓存系统
    mutable QCache<QString, QImage> m_virtualCanvasCache;   // 虚拟画布缓存
    mutable QCache<QString, QImage> m_physicalCanvasCache;  // 物理画布缓存
    mutable QMutex m_cacheMutex;                            // 缓存互斥锁

    // 虚拟画布管理器（后续创建时注入）
    std::unique_ptr<VirtualCanvasManager> m_virtualCanvasManager;

    // 性能统计
    mutable qint64 m_totalRenderTime;                   // 总渲染时间
    mutable int m_renderCount;                          // 渲染次数

    // === 常量定义 ===
    static constexpr int DEFAULT_CACHE_SIZE = 50;      // 默认缓存项数
    static constexpr qint64 MAX_CACHE_MEMORY_MB = 200; // 最大缓存内存（MB）
};

#endif // DUALCANVASRENDERER_H